#include "GenericTypeDefs.h"
#include "USB/usb.h"
#include "HardwareProfile.h"
#include "spi.h"

#define USB_HW_SPI    0

//=============================================================
#define HW_SPI_INIT_EN    0x22
#define HW_SPI_INIT_DIS   0x02
//=============================================================
#define SPI_SCK       7
#define SPI_MISO		6
#define SPI_MOSI		5

/** MISO pin***************************************************/
#define MISO_PORT       B
#define MISO_BIT        4
#define MISO_MASK       ( 1 << MISO_BIT )
#define MISO_TRIS       TRIS( B, 4 )
#define MISO            PORT( B, 4 )
#define INIT_MISO()     MISO_TRIS = INPUT_PIN

/** MOSI ******************************************************/
#define MOSI_PORT        C
#define MOSI_BIT         7
#define MOSI_MASK        ( 1 << MOSI_BIT )
#define MOSI_TRIS        TRIS( C, 7 )
#define MOSI             LATCH( C, 7 )
#define MOSI_CLR()       MOSI = 0
#define MOSI_SET()       MOSI = 1
#define MOSI_TOGGLE()    MOSI = !MOSI
#define INIT_MOSI()      MOSI_CLR(), MOSI_TRIS = OUTPUT_PIN

/** SCK ******************************************************/
#define SCK_PORT        B
#define SCK_BIT         6
#define SCK_MASK        ( 1 << SCK_BIT )
#define SCK_TRIS        TRIS( B, 6 )
#define SCK             LATCH( B, 6 )
#define SCK_CLR()       SCK = 0
#define SCK_SET()        SCK = 1
#define SCK_TOGGLE()    SCK = !SCK
#define INIT_SCK()      SCK_CLR(), SCK_TRIS = OUTPUT_PIN

/** **********************************************************/
#define spi_nop() 

#define SET_SCK()		SCK_SET()
#define CLR_SCK()		SCK_CLR()

#define TOGGLE_SCK()	SCK_TOGGLE()

#define SET_MOSI()	MOSI_SET()
#define CLR_MOSI()	MOSI_CLR()

#define GET_MISO()	MISO

#if USB_HW_SPI
void mosi_ctrl(BYTE level)
{
    SSPCON1 = HW_SPI_INIT_DIS;
    if(level) {
        SSPBUF = 0xFF;
    } else {
        SSPBUF = 0x00;
    }
    SSPCON1 = HW_SPI_INIT_EN;
}

void spi_init(void)
{
	INIT_MISO();
	INIT_MOSI();
	INIT_SCK();

    SSPSTAT = 0x40;
    SSPCON1 = HW_SPI_INIT_EN;
}

BYTE spi_play_one_byte(BYTE data)
{
    PIR1bits.SSPIF = 0;
    SSPBUF = data;
    while( PIR1bits.SSPIF == 0 );

	return SSPBUF;
}

#else //#if USB_HW_SPI

void mosi_ctrl(BYTE level)
{
    if(level) {
        SET_MOSI();
    } else {
        CLR_MOSI();
    }
}

void spi_init(void)
{
	INIT_MISO();
	INIT_MOSI();
	INIT_SCK();
}

BYTE spi_play_one_byte(BYTE data)
{
	BYTE ret_val = 0, mask = 0x80;

	do {
		if(mask & data) {
			SET_MOSI();
		} else {
			CLR_MOSI();
		}
		//delay();
		TOGGLE_SCK();
		//delay();
		if(GET_MISO()) {
			ret_val |= mask;
		}
		mask = mask >> 1;
		TOGGLE_SCK();
		//delay();
	} while(mask);

	return ret_val;
}
#endif //#if USB_HW_SPI
